/* autor Konjkov.VV@gmail.com */

#include <string>
#include <iostream>

#include "Statement.h"
#include "Sqlerr.h"

Statement::Statement(SQLHENV env, SQLHDBC dbc)
{
    this->env;
    this->dbc;
    SQLAllocStmt( dbc, &stmt );
};

void Statement::SetAttr(SQLINTEGER option, SQLPOINTER value){
    SQLRETURN retcode = SQLSetStmtAttr( dbc, option, value, SQL_NTS );
    if ( retcode == SQL_ERROR ) {
        std::cerr << __FILE__ << ":" << __LINE__;
        throw Sqlerr(env, dbc, stmt);
    }
};

void Statement::Prepare(std::string query)
{
SQLSMALLINT colums;
SQLSMALLINT params;

    SQLRETURN retcode = SQLPrepare( stmt, (SQLCHAR*)query.c_str(), SQL_NTS );
    if ( retcode == SQL_ERROR ) {
        std::cerr << __FILE__ << ":" << __LINE__;
        throw Sqlerr(env, dbc, stmt);
    }
//  Add all Columns
    SQLNumResultCols( stmt, &colums);
    for (SQLUSMALLINT numcol = 0; numcol < colums; numcol++) {
        col.push_back(Column(env, dbc, stmt, numcol+1));
    }
// Add all Parameters
    SQLNumParams( stmt, &params);
    for (SQLUSMALLINT numpar = 0; numpar < params; numpar++) {
        par.push_back(Param(env, dbc, stmt, numpar+1));
    }
};

void Statement::ExecDirect(std::string query)
{
SQLSMALLINT columns;
SQLSMALLINT params;

    SQLRETURN retcode = SQLExecDirect( stmt, (SQLCHAR*)query.c_str(), SQL_NTS );
    if ( retcode == SQL_ERROR ) {
        std::cerr << __FILE__ << ":" << __LINE__;
        throw Sqlerr(env, dbc, stmt);
    }
//  Add all Columns
    SQLNumResultCols( stmt, &columns);
    for (SQLUSMALLINT numcol = 0; numcol < columns; numcol++) {
        col.push_back(Column(env, dbc, stmt, numcol+1));
    }
// Add all Parameters
    SQLNumParams( stmt, &params);
    for (SQLUSMALLINT numpar = 0; numpar < params; numpar++) {
        par.push_back(Param(env, dbc, stmt, numpar+1));
    }
};

void Statement::Execute()
{
    SQLRETURN retcode = SQLExecute( stmt );
    if ( retcode == SQL_ERROR ) {
        std::cerr << __FILE__ << ":" << __LINE__;
        throw Sqlerr(env, dbc, stmt);
    }
};

void Statement::Tables(std::string schemaname, std::string tablename, std::string tabletype)
{
SQLSMALLINT columns;

    SQLRETURN retcode = SQLTables( stmt, NULL, 0, (SQLCHAR*)schemaname.c_str(), SQL_NTS, (SQLCHAR*)tablename.c_str(), SQL_NTS, (SQLCHAR*)tabletype.c_str(), SQL_NTS);
    if ( retcode == SQL_ERROR ) {
        std::cerr << __FILE__ << ":" << __LINE__;
        throw Sqlerr(env, dbc, stmt);
    }
//  Add all Columns
    SQLNumResultCols( stmt, &columns);
    for (SQLUSMALLINT numcol = 0; numcol < columns; numcol++) {
        col.push_back(Column(env, dbc, stmt, numcol+1));
    }
};

void Statement::Columns(std::string schemaname, std::string tablename, std::string columnname)
{
SQLSMALLINT columns;

    SQLRETURN retcode = SQLColumns( stmt, NULL, 0, (SQLCHAR*)schemaname.c_str(), SQL_NTS, (SQLCHAR*)tablename.c_str(), SQL_NTS, NULL, 0);
    if ( retcode == SQL_ERROR ) {
        std::cerr << __FILE__ << ":" << __LINE__;
        throw Sqlerr(env, dbc, stmt);
    }
//  Add all Columns
    SQLNumResultCols( stmt, &columns);
    for (SQLUSMALLINT numcol = 0; numcol < columns; numcol++) {
        col.push_back(Column(env, dbc, stmt, numcol+1));
    }
};

void Statement::PrimaryKeys(std::string schemaname, std::string tablename)
{
SQLSMALLINT columns;

    SQLRETURN retcode = SQLPrimaryKeys( stmt, NULL, 0, (SQLCHAR*)schemaname.c_str(), SQL_NTS, (SQLCHAR*)tablename.c_str(), SQL_NTS);
    if ( retcode == SQL_ERROR ) {
        std::cerr << __FILE__ << ":" << __LINE__;
        throw Sqlerr(env, dbc, stmt);
    }
//  Add all Columns
    retcode = SQLNumResultCols( stmt, &columns);
    if ( retcode == SQL_ERROR ) {
        std::cerr << __FILE__ << ":" << __LINE__;
        throw Sqlerr(env, dbc, stmt);
    }
    for (SQLUSMALLINT numcol = 0; numcol < columns; numcol++) {
        col.push_back(Column(env, dbc, stmt, numcol+1));
    }
};

bool Statement::Fetch()
{
    SQLRETURN retcode = SQLFetch( stmt );
    if ( retcode == SQL_ERROR ) {
        std::cerr << __FILE__ << ":" << __LINE__;
        throw Sqlerr(env, dbc, stmt);
    } else if ( retcode == SQL_NO_DATA ) {
        return false;
    } else {
        return true;
    }
};

Statement::~Statement()
{
    SQLFreeStmt( stmt, SQL_CLOSE );
};
